﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ChemicalEquilibrium
{
    public delegate int GetVoltageCallback();

    public class IonicEquilibrium
    {
        Queue<Reactant> Channel, IonIn, IonOut;
        float Conductance;
        int Potential;
        GetVoltageCallback GetVoltage;
        int Count;
        public int GetChannel() { return this.Channel.Count; }
        public int GetIonIn() { return this.IonIn.Count; }
        public int GetIonOut() { return this.IonOut.Count; }
        public int GetCount() { return this.Count; }

        /// <summary>
        /// 离子平衡
        /// </summary>
        /// <param name="channel">离子通道</param>
        /// <param name="ionIn">膜内离子</param>
        /// <param name="ionOut">膜外离子</param>
        /// <param name="conductance">膜电导</param>
        /// <param name="potential">平衡电位</param>
        /// <param name="getVoltage">获取膜电位</param>
        public IonicEquilibrium(Queue<Reactant> channel, Queue<Reactant> ionIn, Queue<Reactant> ionOut, float conductance, int potential, GetVoltageCallback getVoltage)
        {
            this.Channel = channel;
            this.IonIn = ionIn;
            this.IonOut = ionOut;
            this.Conductance = conductance;
            this.Potential = potential;
            this.GetVoltage = getVoltage;
        }

        /// <summary>
        /// 运输离子
        /// </summary>
        public void Transport()
        {
            int voltage = this.GetVoltage();

            this.Count = (int)((voltage - this.Potential) * this.Conductance * this.Channel.Count);

            if (Count > 0 && this.IonIn.Count > 0)
                for (int i = 0; i < Count; i++)
                {
                    if (this.IonIn.Count == 0) break;

                    this.IonOut.Enqueue(this.IonIn.Dequeue());
                }
            else if (Count < 0 && this.IonOut.Count > 0)
                for (int i = 0; i < -Count; i++)
                {
                    if (this.IonOut.Count == 0) break;

                    this.IonIn.Enqueue(this.IonOut.Dequeue());
                }
        }
    }
}
